package service

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"log"
	"math/rand"
	"regexp"
	"time"

	"gitee.com/wangshh_123/cross-pay-go/src/config"
	"gitee.com/wangshh_123/cross-pay-go/src/database"
	"gitee.com/wangshh_123/cross-pay-go/src/models"
	"gitee.com/wangshh_123/cross-pay-go/src/platform/common"
	"gitee.com/wangshh_123/cross-pay-go/src/platform/providers/photonpay"
	photonpayservices "gitee.com/wangshh_123/cross-pay-go/src/platform/providers/photonpay/services"
	"gitee.com/wangshh_123/cross-pay-go/src/utils/auth"
	commonUtils "gitee.com/wangshh_123/cross-pay-go/src/utils/common"
	commUtils "gitee.com/wangshh_123/cross-pay-go/src/utils/communication"

	"github.com/redis/go-redis/v9"
	"github.com/shopspring/decimal"
	"golang.org/x/crypto/bcrypt"
	"gorm.io/gorm"
)

// MatrixAccountResponse PhotonPay矩阵账户创建响应
type MatrixAccountResponse struct {
	Code string `json:"code"`
	Msg  string `json:"msg"`
	Data struct {
		MatrixAccount string `json:"matrixAccount"`
	} `json:"data"`
}

// UserService 用户服务
type UserService struct {
	db *gorm.DB
}

// NewUserService 创建用户服务
func NewUserService() *UserService {
	return &UserService{
		db: database.DB,
	}
}

// VerifyInvitationCode 验证邀请码
func (s *UserService) VerifyInvitationCode(code string) error {
	ctx := context.Background()
	key := fmt.Sprintf("invitation:code:%s", code)

	// 从Redis获取邀请码信息
	exists, err := database.RedisClient.Exists(ctx, key).Result()
	if err != nil {
		return fmt.Errorf("验证邀请码失败: %v", err)
	}

	if exists == 0 {
		return errors.New("邀请码无效或已过期")
	}

	return nil
}

// getCurrentMonthPlatform 获取当前月份应该使用的平台
func (s *UserService) getCurrentMonthPlatform() string {
	return config.GetCurrentMonthPlatform()
}

// generateHlPayMatrixAccount 生成HlPay矩阵账户
func (s *UserService) generateHlPayMatrixAccount(username string, isSubAccount bool) (*models.UserMatrixAccount, error) {
	var matrixAccount string

	if isSubAccount {
		// 子账号：生成SUB前缀的矩阵账户
		matrixAccount = fmt.Sprintf("SUB%s", commonUtils.GenerateRandomString(8))
	} else {
		// 主账号：生成HL前缀的矩阵账户，格式类似：HL + 时间戳（精确到毫秒）+ 随机数
		// 确保总长度合适，类似MI1937709743208407040的格式
		timestamp := time.Now().UnixMilli() // 使用毫秒时间戳，更短
		randomNum := rand.Intn(100000)      // 生成5位随机数
		matrixAccount = fmt.Sprintf("HL%d%05d", timestamp, randomNum)
	}

	return &models.UserMatrixAccount{
		MatrixAccount:         matrixAccount,
		MatrixAccountName:     username,
		PlatformType:          "hlpay",
		Status:                "active",
		TotalTransferAmount:   decimal.Zero,
		ParentMatrixAccountID: nil,
	}, nil
}

// Register 用户注册
func (s *UserService) Register(username, password, email, phone, name, invitationCode string) (*models.User, error) {
	// 检查用户名是否已存在
	var existingUser models.User
	if err := s.db.Where("username = ?", username).First(&existingUser).Error; err == nil {
		return nil, errors.New("username already exists")
	}

	// 检查邮箱是否已存在
	if err := s.db.Where("email = ?", email).First(&existingUser).Error; err == nil {
		return nil, errors.New("email already exists")
	}

	// 如果提供了手机号，检查是否已存在
	if phone != "" {
		if err := s.db.Where("phone = ?", phone).First(&existingUser).Error; err == nil {
			return nil, errors.New("phone number already exists")
		}
	}

	// 加密密码
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	if err != nil {
		return nil, err
	}

	// 开始数据库事务
	tx := s.db.Begin()
	if tx.Error != nil {
		return nil, tx.Error
	}

	// 创建用户
	user := &models.User{
		Username: username,
		Password: string(hashedPassword),
		Email:    email,
		Phone:    phone,
		Name:     name,
		RoleID:   2, // 默认角色ID为2
		Status:   1, // 默认状态为正常
	}

	if err := tx.Create(user).Error; err != nil {
		tx.Rollback()
		return nil, err
	}

	// 如果提供了邀请码，验证其有效性并获取父级矩阵账户
	var parentMatrixAccountID *int64
	var masterAccountID int64
	var subAccountConfig struct {
		UserID      int64                  `json:"user_id"`
		AccountName string                 `json:"account_name"`
		Role        string                 `json:"role"`
		Permissions map[string]interface{} `json:"permissions"`
	}

	if invitationCode != "" {
		// 获取邀请码信息
		ctx := context.Background()
		key := fmt.Sprintf("invitation:code:%s", invitationCode)
		jsonData, err := database.RedisClient.Get(ctx, key).Result()
		if err != nil {
			// 如果邀请码不存在或已过期，继续注册流程，但不使用邀请码
			log.Printf("邀请码无效或已过期: %v", err)
			invitationCode = ""
		} else {
			// 解析邀请码数据
			if err := json.Unmarshal([]byte(jsonData), &subAccountConfig); err != nil {
				return nil, fmt.Errorf("解析邀请码数据失败: %v", err)
			}

			// 获取邀请人的主账号信息
			var masterAccount models.MasterAccount
			if err := s.db.Where("user_id = ?", subAccountConfig.UserID).First(&masterAccount).Error; err != nil {
				return nil, fmt.Errorf("获取邀请人主账号失败: %v", err)
			}
			masterAccountID = masterAccount.ID

			// 获取邀请人的矩阵账户
			var inviterMatrixAccount models.UserMatrixAccount
			if err := s.db.Where("user_id = ?", subAccountConfig.UserID).First(&inviterMatrixAccount).Error; err != nil {
				return nil, fmt.Errorf("获取邀请人矩阵账户失败: %v", err)
			}
			parentMatrixAccountID = &inviterMatrixAccount.ID
		}
	}

	// 创建矩阵账户
	var matrixAccount *models.UserMatrixAccount

	if invitationCode == "" {
		// 创建用户角色关联
		userRole := &models.UserRole{
			UserID: int64(user.ID),
			RoleID: user.RoleID,
		}

		if err := tx.Create(userRole).Error; err != nil {
			tx.Rollback()
			return nil, fmt.Errorf("创建用户角色关联失败: %v", err)
		}

		// 根据配置决定使用哪个平台
		if s.getCurrentMonthPlatform() == "hlpay" {
			// 使用HlPay平台
			log.Printf("用户 %s 注册，根据配置使用HlPay平台", username)

			// 生成HlPay矩阵账户
			hlPayMatrixAccount, err := s.generateHlPayMatrixAccount(username, false)
			if err != nil {
				tx.Rollback()
				return nil, fmt.Errorf("生成HlPay矩阵账户失败: %v", err)
			}

			hlPayMatrixAccount.UserID = int64(user.ID)
			matrixAccount = hlPayMatrixAccount

			// 先创建矩阵账户记录
			if err := tx.Create(matrixAccount).Error; err != nil {
				tx.Rollback()
				return nil, fmt.Errorf("创建矩阵账户记录失败: %v", err)
			}

			// 创建HlPay账户余额记录
			hlPayBalance := &models.HlPayAccountBalance{
				AccountNo:       fmt.Sprintf("HL-USD%d", time.Now().UnixNano()), // 生成HL-USD格式的账户号，后面跟数字
				Currency:        "USD",                                          // 默认USD
				MemberID:        fmt.Sprintf("%d", user.ID),                     // 用户ID作为会员ID
				OwnerNo:         hlPayMatrixAccount.MatrixAccount,               // 矩阵账户号
				OwnerType:       "matrix",                                       // 默认矩阵账户类型
				RealTimeBalance: decimal.NewFromFloat(0),                        // 初始余额为0
				Status:          "active",                                       // 默认活跃状态
			}

			if err := tx.Create(hlPayBalance).Error; err != nil {
				tx.Rollback()
				return nil, fmt.Errorf("创建HlPay账户余额记录失败: %v", err)
			}

		} else {
			// 使用PhotonPay平台
			log.Printf("用户 %s 注册，根据配置使用PhotonPay平台", username)

			// 创建新的PhotonPay矩阵账户
			ctx := context.Background()
			platformConfig := &common.PlatformConfig{
				AppID:      config.GlobalConfig.PhotonPay.AppID,
				AppSecret:  config.GlobalConfig.PhotonPay.AppSecret,
				GatewayURL: config.GlobalConfig.PhotonPay.GatewayURL,
			}
			client := photonpay.NewPhotonPayClient(platformConfig)

			// 准备创建矩阵账户的请求体
			requestBody := map[string]interface{}{
				"matrixAccountName": username,
			}

			bodyBytes, err := json.Marshal(requestBody)
			if err != nil {
				tx.Rollback()
				return nil, fmt.Errorf("准备矩阵账户创建请求失败: %v", err)
			}

			// 调用PhotonPay API创建矩阵账户
			resp, err := photonpayservices.CreateMatrixAccount(ctx, client, bodyBytes)
			if err != nil {
				tx.Rollback()
				return nil, fmt.Errorf("创建矩阵账户失败: %v", err)
			}

			// 解析响应
			var matrixResp MatrixAccountResponse
			if err := json.Unmarshal(resp, &matrixResp); err != nil {
				tx.Rollback()
				return nil, fmt.Errorf("解析矩阵账户响应失败: %v", err)
			}

			if matrixResp.Code != "0000" {
				tx.Rollback()
				return nil, fmt.Errorf("创建矩阵账户失败: %s", matrixResp.Msg)
			}

			matrixAccount = &models.UserMatrixAccount{
				UserID:                int64(user.ID),
				MatrixAccount:         matrixResp.Data.MatrixAccount,
				MatrixAccountName:     username,
				PlatformType:          "photonpay",
				Status:                "active",
				TotalTransferAmount:   decimal.Zero,
				ParentMatrixAccountID: nil,
			}
		}
	} else {
		// 创建用户角色关联
		userRole := &models.UserRole{
			UserID: int64(user.ID),
			RoleID: 5,
		}

		if err := tx.Create(userRole).Error; err != nil {
			tx.Rollback()
			return nil, fmt.Errorf("创建用户角色关联失败: %v", err)
		}

		// 如果有邀请码，根据月份决定使用哪个平台
		if s.getCurrentMonthPlatform() == "hlpay" {
			// 使用HlPay平台
			hlPayMatrixAccount, err := s.generateHlPayMatrixAccount(username, true)
			if err != nil {
				tx.Rollback()
				return nil, fmt.Errorf("生成HlPay矩阵账户失败: %v", err)
			}

			hlPayMatrixAccount.UserID = int64(user.ID)
			hlPayMatrixAccount.ParentMatrixAccountID = parentMatrixAccountID
			matrixAccount = hlPayMatrixAccount

			// 先创建矩阵账户记录
			if err := tx.Create(matrixAccount).Error; err != nil {
				tx.Rollback()
				return nil, fmt.Errorf("创建矩阵账户记录失败: %v", err)
			}

			// 创建HlPay账户余额记录（子账号）
			hlPayBalance := &models.HlPayAccountBalance{
				AccountNo:       fmt.Sprintf("HL-USD%d", time.Now().UnixNano()), // 生成HL-USD格式的账户号，后面跟数字
				Currency:        "USD",                                          // 默认USD
				MemberID:        fmt.Sprintf("%d", user.ID),                     // 用户ID作为会员ID
				OwnerNo:         hlPayMatrixAccount.MatrixAccount,               // 矩阵账户号
				OwnerType:       "matrix",                                       // 默认矩阵账户类型
				RealTimeBalance: decimal.NewFromFloat(0),                        // 初始余额为0
				Status:          "active",                                       // 默认活跃状态
			}

			if err := tx.Create(hlPayBalance).Error; err != nil {
				tx.Rollback()
				return nil, fmt.Errorf("创建HlPay账户余额记录失败: %v", err)
			}
		} else {
			// 使用PhotonPay平台
			matrixAccount = &models.UserMatrixAccount{
				UserID:                int64(user.ID),
				MatrixAccount:         fmt.Sprintf("SUB%s", commonUtils.GenerateRandomString(8)),
				MatrixAccountName:     username,
				PlatformType:          "photonpay",
				Status:                "active",
				TotalTransferAmount:   decimal.Zero,
				ParentMatrixAccountID: parentMatrixAccountID,
			}
		}
	}

	// 创建矩阵账户记录（只对PhotonPay平台）
	if matrixAccount != nil && matrixAccount.PlatformType == "photonpay" {
		if err := tx.Create(matrixAccount).Error; err != nil {
			tx.Rollback()
			return nil, fmt.Errorf("创建矩阵账户记录失败: %v", err)
		}
	}

	if invitationCode != "" {
		// 创建子账号记录
		permissionsJSON, err := json.Marshal(subAccountConfig.Permissions)
		if err != nil {
			tx.Rollback()
			return nil, fmt.Errorf("序列化权限配置失败: %v", err)
		}

		subAccount := &models.SubAccount{
			MasterAccountID: masterAccountID,
			UserID:          int64(user.ID),
			AccountName:     subAccountConfig.AccountName,
			Role:            "sub_user",
			Permissions:     string(permissionsJSON),
			Status:          "active",
		}

		if err := tx.Create(subAccount).Error; err != nil {
			tx.Rollback()
			return nil, fmt.Errorf("创建子账号失败: %v", err)
		}
	}

	// 如果使用了邀请码，在Redis中标记该邀请码已被使用
	if invitationCode != "" {
		usedKey := fmt.Sprintf("invitation:used:%s", invitationCode)
		// 设置邀请码使用记录，有效期30天
		err = database.RedisClient.Set(context.Background(), usedKey, user.ID, 30*24*time.Hour).Err()
		if err != nil {
			// 记录错误但不影响注册流程
			log.Printf("记录邀请码使用失败: %v", err)
		}
	}

	// 提交事务
	if err := tx.Commit().Error; err != nil {
		return nil, err
	}
	return user, nil
}

// Login 用户登录
func (s *UserService) Login(username, password string) (*models.User, error) {
	var user models.User
	if err := s.db.Where("username = ?", username).First(&user).Error; err != nil {
		return nil, errors.New("user not found")
	}

	// 验证密码
	if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil {
		return nil, errors.New("invalid password")
	}

	return &user, nil
}

// GetUserByID 根据ID获取用户（只查未删除）
func (s *UserService) GetUserByID(id int64) (*models.User, error) {
	var user models.User
	if err := s.db.Where("id = ? AND is_deleted = 0", id).First(&user).Error; err != nil {
		return nil, err
	}
	return &user, nil
}

// UpdateUser 更新用户信息
func (s *UserService) UpdateUser(id int64, email, phone, name string, roleID int64, status int8) (*models.User, error) {
	var user models.User
	if err := s.db.First(&user, id).Error; err != nil {
		return nil, err
	}

	// 如果提供了新邮箱，检查是否已存在
	if email != "" && email != user.Email {
		var existingUser models.User
		if err := s.db.Where("email = ?", email).First(&existingUser).Error; err == nil {
			return nil, errors.New("email already exists")
		}
		user.Email = email
	}

	// 如果提供了新手机号，检查是否已存在
	if phone != "" && phone != user.Phone {
		var existingUser models.User
		if err := s.db.Where("phone = ?", phone).First(&existingUser).Error; err == nil {
			return nil, errors.New("phone number already exists")
		}
		user.Phone = phone
	}

	// 更新姓名
	if name != "" {
		user.Name = name
	}

	// 更新角色ID
	if roleID > 0 {
		user.RoleID = roleID
	}

	// 更新状态
	if status >= 0 {
		user.Status = status
	}

	user.UpdatedAt = time.Now()
	if err := s.db.Save(&user).Error; err != nil {
		return nil, err
	}

	return &user, nil
}

// ChangePassword 修改密码
func (s *UserService) ChangePassword(id int64, oldPassword, newPassword string) error {
	var user models.User
	if err := s.db.First(&user, id).Error; err != nil {
		return err
	}

	// 验证旧密码
	if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(oldPassword)); err != nil {
		return errors.New("invalid old password")
	}

	// 加密新密码
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(newPassword), bcrypt.DefaultCost)
	if err != nil {
		return err
	}

	user.Password = string(hashedPassword)
	user.UpdatedAt = time.Now()
	return s.db.Save(&user).Error
}

// ListUsers 获取用户列表（只查未删除，支持模糊搜索，排除roleid=1和roleid=6的用户）
func (s *UserService) ListUsers(page, pageSize int, keyword string, departmentID *int64, sortBy, sortOrder string) ([]models.User, int64, error) {
	var users []models.User
	var total int64

	// 构建查询，排除已删除的用户和特定角色ID的用户
	db := s.db.Model(&models.User{}).
		Joins("LEFT JOIN user_roles ON users.id = user_roles.user_id").
		Joins("LEFT JOIN roles ON user_roles.role_id = roles.id").
		Where("users.is_deleted = 0").
		Where("(roles.id IS NULL OR (roles.id != 1 AND roles.id != 6))")

	// 如果指定了部门ID，添加部门筛选条件
	if departmentID != nil {
		db = db.Joins("JOIN department_users ON users.id = department_users.user_id").
			Where("department_users.department_id = ? AND department_users.status = 'active'", *departmentID)
	}

	if keyword != "" {
		like := "%" + keyword + "%"
		db = db.Where("users.name LIKE ? OR users.email LIKE ? OR users.phone LIKE ?", like, like, like)
	}

	// 获取总数
	if err := db.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 处理排序参数
	if sortBy == "" {
		sortBy = "created_at" // 默认按创建时间排序
	}
	if sortOrder == "" {
		sortOrder = "desc" // 默认倒序
	}

	// 验证排序字段
	allowedSortFields := map[string]string{
		"created_at":      "users.created_at",
		"updated_at":      "users.updated_at",
		"last_login_time": "users.last_login_time",
		"username":        "users.username",
		"email":           "users.email",
		"name":            "users.name",
		"status":          "users.status",
	}

	sortField, exists := allowedSortFields[sortBy]
	if !exists {
		sortField = "users.created_at" // 如果字段不存在，使用默认字段
	}

	// 验证排序方向
	if sortOrder != "asc" && sortOrder != "desc" {
		sortOrder = "desc" // 如果方向无效，使用默认方向
	}

	// 分页查询
	offset := (page - 1) * pageSize
	if err := db.Select("users.*").
		Offset(offset).
		Limit(pageSize).
		Order(fmt.Sprintf("%s %s", sortField, sortOrder)).
		Find(&users).Error; err != nil {
		return nil, 0, err
	}

	return users, total, nil
}

// DeleteUser 软删除用户
func (s *UserService) DeleteUser(id int64) error {
	return s.db.Model(&models.User{}).
		Where("id = ?", id).
		Update("is_deleted", 1).Error
}

// VerifyCode 验证验证码
func (s *UserService) VerifyCode(phone, code, purpose string) (bool, error) {
	ctx := context.Background()
	key := fmt.Sprintf("sms:verification:%s:%s", purpose, phone)

	// 从Redis获取验证码
	savedCode, err := database.RedisClient.Get(ctx, key).Result()
	if err == redis.Nil {
		return false, errors.New("验证码已过期")
	} else if err != nil {
		return false, fmt.Errorf("获取验证码失败: %v", err)
	}

	// 验证码比对
	if savedCode != code {
		return false, errors.New("验证码错误")
	}

	// 验证成功后删除验证码
	err = database.RedisClient.Del(ctx, key).Err()
	if err != nil {
		return false, fmt.Errorf("删除验证码失败: %v", err)
	}

	return true, nil
}

// GenerateInvitationCode 生成邀请码
func (s *UserService) GenerateInvitationCode(userID int64, accountName, role string, permissions map[string]interface{}, expiresIn time.Duration) (string, error) {
	ctx := context.Background()

	// 生成8位随机邀请码
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	code := fmt.Sprintf("INV%06d", r.Intn(1000000))

	// 准备存储的数据
	invitationData := map[string]interface{}{
		"user_id":      userID,
		"account_name": accountName,
		"role":         role,
		"permissions":  permissions,
	}

	// 将数据序列化为JSON
	jsonData, err := json.Marshal(invitationData)
	if err != nil {
		return "", fmt.Errorf("序列化邀请码数据失败: %v", err)
	}

	// 存储到Redis，设置过期时间
	key := fmt.Sprintf("invitation:code:%s", code)
	err = database.RedisClient.Set(ctx, key, jsonData, expiresIn).Err()
	if err != nil {
		return "", fmt.Errorf("生成邀请码失败: %v", err)
	}

	return code, nil
}

// FindByLoginID 通过登录ID（用户名、邮箱或手机号）查找用户
func (s *UserService) FindByLoginID(loginID string) (*models.User, error) {
	var user models.User
	err := s.db.Unscoped().Where("username = ? OR email = ? OR phone = ?", loginID, loginID, loginID).First(&user).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("用户不存在")
		}
		return nil, err
	}
	return &user, nil
}

// FindByID 通过ID查找用户
func (s *UserService) FindByID(id int64) (*models.User, error) {
	var user models.User
	err := s.db.First(&user, id).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("用户不存在")
		}
		return nil, err
	}
	return &user, nil
}

// ValidatePassword 验证用户密码
func (s *UserService) ValidatePassword(user *models.User, password string) bool {
	err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password))
	return err == nil
}

// Update 更新用户信息
func (s *UserService) Update(user *models.User) error {
	return s.db.Save(user).Error
}

// GetUserAuthMethods 获取用户的认证方式
func (s *UserService) GetUserAuthMethods(userID int64) ([]models.UserAuthMethod, error) {
	var methods []models.UserAuthMethod
	err := s.db.Where("user_id = ?", userID).Order("priority").Find(&methods).Error
	return methods, err
}

// GetLastLoginRecord 获取用户最近的登录记录
func (s *UserService) GetLastLoginRecord(userID int64) (*models.UserLoginRecord, error) {
	var record models.UserLoginRecord
	err := s.db.Where("user_id = ?", userID).Order("login_time DESC").First(&record).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, nil
		}
		return nil, err
	}
	return &record, nil
}

// CreateLoginRecord 创建登录记录
func (s *UserService) CreateLoginRecord(record *models.UserLoginRecord) error {
	return s.db.Create(record).Error
}

// CreateUser 创建新用户
func (s *UserService) CreateUser(user *models.User) error {
	// 检查用户名、邮箱和手机号是否已存在
	var count int64
	s.db.Model(&models.User{}).Where("username = ? OR email = ? OR phone = ?",
		user.Username, user.Email, user.Phone).Count(&count)
	if count > 0 {
		return errors.New("用户名、邮箱或手机号已存在")
	}

	// 加密密码
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(user.Password), bcrypt.DefaultCost)
	if err != nil {
		return err
	}
	user.Password = string(hashedPassword)

	// 设置默认值
	user.Status = 1
	user.RoleID = 1
	user.CreatedAt = time.Now()
	user.UpdatedAt = time.Now()

	return s.db.Create(user).Error
}

// UpdateUserAuthMethod 更新用户认证方式
func (s *UserService) UpdateUserAuthMethod(method *models.UserAuthMethod) error {
	return s.db.Save(method).Error
}

// CreateUserAuthMethod 创建用户认证方式
func (s *UserService) CreateUserAuthMethod(method *models.UserAuthMethod) error {
	return s.db.Create(method).Error
}

// CheckAuthMethodExists 检查用户是否已存在指定类型的认证方式
func (s *UserService) CheckAuthMethodExists(userID int64, authType string) (bool, error) {
	var count int64
	err := s.db.Model(&models.UserAuthMethod{}).
		Where("user_id = ? AND auth_type = ?", userID, authType).
		Count(&count).Error
	if err != nil {
		return false, err
	}
	return count > 0, nil
}

// ForgotPassword 通过验证码重置密码
func (s *UserService) ForgotPassword(email, phone, code, newPassword string) error {
	// 验证参数
	if (email == "" && phone == "") || code == "" || newPassword == "" {
		return errors.New("缺少必要参数")
	}

	// 验证密码格式
	if len(newPassword) < 8 {
		return errors.New("密码长度必须至少为8个字符")
	}

	// 检查是否包含字母
	if !regexp.MustCompile(`[A-Za-z]`).MatchString(newPassword) {
		return errors.New("密码必须包含至少一个字母")
	}

	// 检查是否包含数字
	if !regexp.MustCompile(`\d`).MatchString(newPassword) {
		return errors.New("密码必须包含至少一个数字")
	}

	// 检查是否包含特殊字符
	if !regexp.MustCompile(`[@$!%*#?&]`).MatchString(newPassword) {
		return errors.New("密码必须包含至少一个特殊字符(@$!%*#?&)")
	}

	// 验证验证码
	var err error
	if email != "" {
		// 验证邮箱验证码
		err = s.VerifyEmailCode(email, code)
	} else {
		// 验证短信验证码
		var valid bool
		valid, err = s.VerifyCode(phone, code, "reset_password")
		if err == nil && !valid {
			err = errors.New("验证码错误")
		}
	}
	if err != nil {
		return err
	}

	// 查找用户
	var user models.User
	query := s.db.Model(&models.User{})
	if email != "" {
		query = query.Where("email = ?", email)
	} else {
		query = query.Where("phone = ?", phone)
	}
	if err := query.First(&user).Error; err != nil {
		return errors.New("用户不存在")
	}

	// 生成密码哈希
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(newPassword), bcrypt.DefaultCost)
	if err != nil {
		return err
	}

	// 更新密码
	if err := s.db.Model(&user).Update("password", string(hashedPassword)).Error; err != nil {
		return err
	}

	return nil
}

// SendForgotPasswordEmailCode 发送忘记密码邮箱验证码
func (s *UserService) SendForgotPasswordEmailCode(email string) error {
	// 验证邮箱格式
	emailRegex := regexp.MustCompile(`^[^\s@]+@[^\s@]+\.[^\s@]+$`)
	if !emailRegex.MatchString(email) {
		return errors.New("邮箱格式不正确")
	}

	// 检查邮箱是否存在
	var user models.User
	if err := s.db.Where("email = ?", email).First(&user).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return errors.New("邮箱不存在")
		}
		return err
	}

	// 创建邮件工具实例
	emailUtil, err := commUtils.NewEmailUtil()
	if err != nil {
		return fmt.Errorf("创建邮件工具失败: %v", err)
	}

	// 发送验证码
	if err := emailUtil.SendResetPasswordCode(email); err != nil {
		return fmt.Errorf("发送验证码失败: %v", err)
	}

	return nil
}

// SendForgotPasswordSmsCode 发送忘记密码短信验证码
func (s *UserService) SendForgotPasswordSmsCode(phone string) error {
	// 验证手机号格式
	phoneRegex := regexp.MustCompile(`^1[3-9]\d{9}$`)
	if !phoneRegex.MatchString(phone) {
		return errors.New("手机号格式不正确")
	}

	// 检查手机号是否存在
	var user models.User
	if err := s.db.Where("phone = ?", phone).First(&user).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return errors.New("手机号不存在")
		}
		return err
	}

	// 创建短信工具实例
	smsUtil, err := commUtils.NewSmsUtil()
	if err != nil {
		return fmt.Errorf("创建短信工具失败: %v", err)
	}

	// 发送验证码
	if err := smsUtil.SendVerificationCode(phone, "reset_password"); err != nil {
		return fmt.Errorf("发送验证码失败: %v", err)
	}

	return nil
}

// VerifyEmailCode 验证邮箱验证码
func (s *UserService) VerifyEmailCode(email, code string) error {
	// 创建邮件工具实例
	emailUtil, err := commUtils.NewEmailUtil()
	if err != nil {
		return fmt.Errorf("创建邮件工具失败: %v", err)
	}

	// 验证验证码
	valid, err := emailUtil.VerifyResetPasswordCode(email, code)
	if err != nil {
		return err
	}
	if !valid {
		return errors.New("验证码错误")
	}

	return nil
}

// CreateUserRole 创建用户角色关联
func (s *UserService) CreateUserRole(userRole *models.UserRole) error {
	// 检查是否已存在相同的用户角色关联
	var count int64
	if err := s.db.Model(&models.UserRole{}).
		Where("user_id = ? AND role_id = ?", userRole.UserID, userRole.RoleID).
		Count(&count).Error; err != nil {
		return err
	}
	if count > 0 {
		return errors.New("user role already exists")
	}

	// 创建用户角色关联
	return s.db.Create(userRole).Error
}

// DeleteUserRole 删除用户角色关联
func (s *UserService) DeleteUserRole(id string) error {
	return s.db.Delete(&models.UserRole{}, id).Error
}

// GetUserRoles 获取用户角色列表
func (s *UserService) GetUserRoles(userID string) ([]models.UserRole, error) {
	var roles []models.UserRole
	if err := s.db.Where("user_id = ?", userID).Find(&roles).Error; err != nil {
		return nil, err
	}
	return roles, nil
}

// GetRoleByID 根据ID获取角色
func (s *UserService) GetRoleByID(roleID int64) (*models.Role, error) {
	var role models.Role
	if err := s.db.First(&role, roleID).Error; err != nil {
		return nil, err
	}
	return &role, nil
}

// ValidateUserExists 验证用户是否存在
func (s *UserService) ValidateUserExists(userID int64) error {
	var count int64
	if err := s.db.Model(&models.User{}).Where("id = ?", userID).Count(&count).Error; err != nil {
		return err
	}
	if count == 0 {
		return errors.New("user not found")
	}
	return nil
}

// ValidateRoleExists 验证角色是否存在
func (s *UserService) ValidateRoleExists(roleID int64) error {
	var count int64
	if err := s.db.Model(&models.Role{}).Where("id = ?", roleID).Count(&count).Error; err != nil {
		return err
	}
	if count == 0 {
		return errors.New("role not found")
	}
	return nil
}

func (s *UserService) AssignRoleToUser(userID int64, roleID int64) error {
	// 直接更新用户的角色
	if err := s.db.Model(&models.UserRole{}).
		Where("user_id = ?", userID).
		Update("role_id", roleID).Error; err != nil {
		// 如果更新失败（可能是因为记录不存在），则创建新记录
		userRole := models.UserRole{
			UserID: userID,
			RoleID: roleID,
		}
		return s.db.Create(&userRole).Error
	}
	return nil
}

// GetUserInfoWithRole 返回用户基本信息和 user_roles 表中的实际角色ID
func (s *UserService) GetUserInfoWithRole(userID int64) (*models.UserInfo, error) {
	var userInfo models.UserInfo
	err := s.db.Model(&models.User{}).
		Select("id, username, email, phone, status, created_at").
		Where("id = ?", userID).
		First(&userInfo).Error
	if err != nil {
		return nil, err
	}

	// 查 user_roles 表
	var userRole models.UserRole
	if err := s.db.Model(&models.UserRole{}).
		Where("user_id = ?", userID).
		Order("id ASC").
		First(&userRole).Error; err == nil {
		userInfo.RoleID = userRole.RoleID
	} else {
		userInfo.RoleID = 2 // fallback 默认角色
	}
	return &userInfo, nil
}

// ValidatePasswordRaw 直接校验密码 hash
func (s *UserService) ValidatePasswordRaw(hashedPwd, plainPwd string) bool {
	return bcrypt.CompareHashAndPassword([]byte(hashedPwd), []byte(plainPwd)) == nil
}

// DB 返回数据库实例
func (s *UserService) DB() *gorm.DB { return s.db }

// GetUserProfileWithRole 返回完整的用户资料和 user_roles 表中的实际角色ID
func (s *UserService) GetUserProfileWithRole(userID int64) (*models.UserProfileResponse, error) {
	var user models.User
	err := s.db.Model(&models.User{}).
		Where("id = ?", userID).
		First(&user).Error
	if err != nil {
		return nil, err
	}

	// 查 user_roles 表
	var userRole models.UserRole
	if err := s.db.Model(&models.UserRole{}).
		Where("user_id = ?", userID).
		Order("id ASC").
		First(&userRole).Error; err == nil {
		user.RoleID = userRole.RoleID
	} else {
		user.RoleID = 2 // fallback 默认角色
	}

	profile := &models.UserProfileResponse{
		ID:             user.ID,
		Username:       user.Username,
		Email:          user.Email,
		Phone:          user.Phone,
		Name:           user.Name,
		Status:         int(user.Status),
		LastLoginTime:  &user.LastLoginTime,
		LastLoginIP:    user.LastLoginIP,
		CreatedAt:      user.CreatedAt,
		UpdatedAt:      user.UpdatedAt,
		InvitationCode: user.InvitationCode,
		RoleID:         user.RoleID,
	}
	return profile, nil
}

// GetGoogleAuthenticatorQRCode 获取谷歌验证器二维码
func (s *UserService) GetGoogleAuthenticatorQRCode(userID int64) (string, string, error) {
	// 检查是否已存在谷歌验证器绑定
	exists, err := s.CheckAuthMethodExists(userID, "ga")
	if err != nil {
		return "", "", err
	}
	if exists {
		return "", "", errors.New("ga_already_bound")
	}

	// 生成密钥
	gaUtil := auth.NewGAUtil()
	secret, err := gaUtil.GenerateSecret()
	if err != nil {
		return "", "", fmt.Errorf("generate_secret_failed: %v", err)
	}

	// 获取用户信息
	user, err := s.GetUserByID(userID)
	if err != nil {
		return "", "", err
	}

	// 生成二维码
	qrCode, err := gaUtil.GenerateQRCode(secret, user.Email, "GoPay跨境支付")
	if err != nil {
		return "", "", fmt.Errorf("generate_qrcode_failed: %v", err)
	}

	return qrCode, secret, nil
}

// BindGoogleAuthenticator 绑定谷歌验证器
func (s *UserService) BindGoogleAuthenticator(userID int64, code string, secret string) error {
	// 检查是否已存在谷歌验证器绑定
	exists, err := s.CheckAuthMethodExists(userID, "ga")
	if err != nil {
		return err
	}
	if exists {
		return errors.New("ga_already_bound")
	}

	// 获取用户信息
	user, err := s.GetUserByID(userID)
	if err != nil {
		return err
	}

	// 验证用户输入的验证码
	gaUtil := auth.NewGAUtil()
	if !gaUtil.VerifyToken(secret, code) {
		return errors.New("invalid_ga_code")
	}

	// 生成二维码
	qrCode, err := gaUtil.GenerateQRCode(secret, user.Email, "GoPay跨境支付")
	if err != nil {
		return fmt.Errorf("generate_qrcode_failed: %v", err)
	}

	// 创建认证方式记录
	authConfig := map[string]interface{}{
		"qr_code": qrCode,
	}
	authConfigJSON, err := json.Marshal(authConfig)
	if err != nil {
		return fmt.Errorf("serialize_auth_config_failed: %v", err)
	}

	authMethod := &models.UserAuthMethod{
		UserID:     userID,
		AuthType:   "ga",
		AuthSecret: secret,
		AuthConfig: string(authConfigJSON),
		IsEnabled:  1,
		Priority:   1,
	}

	if err := s.CreateUserAuthMethod(authMethod); err != nil {
		return fmt.Errorf("create_auth_method_failed: %v", err)
	}

	return nil
}

// UnbindGoogleAuthenticator 解绑谷歌验证器
func (s *UserService) UnbindGoogleAuthenticator(userID int64) error {
	// 检查是否存在谷歌验证器绑定
	exists, err := s.CheckAuthMethodExists(userID, "ga")
	if err != nil {
		return err
	}
	if !exists {
		return errors.New("ga_not_bound")
	}

	// 删除认证方式记录
	return s.db.Where("user_id = ? AND auth_type = ?", userID, "ga").Delete(&models.UserAuthMethod{}).Error
}

// VerifyGoogleAuthenticator 验证谷歌验证器
func (s *UserService) VerifyGoogleAuthenticator(userID int64, code string) (bool, error) {
	// 获取用户的谷歌验证器配置
	var authMethod models.UserAuthMethod
	if err := s.db.Where("user_id = ? AND auth_type = ?", userID, "ga").First(&authMethod).Error; err != nil {
		return false, errors.New("ga_not_bound")
	}

	// 验证验证码
	gaUtil := auth.NewGAUtil()
	return gaUtil.VerifyToken(authMethod.AuthSecret, code), nil
}

// GetAccountBalance 获取账户余额
func (s *UserService) GetAccountBalance(userID int64) (decimal.Decimal, error) {
	// 先查询用户角色
	var userRole models.UserRole
	if err := s.db.Where("user_id = ?", userID).First(&userRole).Error; err != nil {
		return decimal.Zero, err
	}

	// 根据角色ID决定查询哪个表
	switch userRole.RoleID {
	case 2, 3, 1: // 主账号角色
		var masterAccount models.MasterAccount
		if err := s.db.Where("user_id = ?", userID).First(&masterAccount).Error; err != nil {
			return decimal.Zero, err
		}
		return masterAccount.Balance, nil
	case 5: // 子账号角色
		var subAccount models.SubAccount
		if err := s.db.Where("user_id = ?", userID).First(&subAccount).Error; err != nil {
			return decimal.Zero, err
		}
		return subAccount.Balance, nil
	default:
		return decimal.Zero, fmt.Errorf("unknown role id: %d", userRole.RoleID)
	}
}

// GetUserMatrixAccount 获取用户的 Matrix 账户信息
func (s *UserService) GetUserMatrixAccount(userID int64) (*models.UserMatrixAccount, error) {
	var matrixAccount models.UserMatrixAccount
	if err := s.db.Where("user_id = ? AND status = ?", userID, "active").First(&matrixAccount).Error; err != nil {
		return nil, err
	}

	// 获取账户余额
	balance, err := s.GetAccountBalance(userID)
	if err != nil {
		if err != gorm.ErrRecordNotFound {
			return nil, err
		}
		balance = decimal.Zero
	}

	// 将余额转换为字符串，保留两位小数，赋值给 Balance 字段
	matrixAccount.Balance = balance.StringFixed(2)

	return &matrixAccount, nil
}

// GetUserAuthMethod 获取用户的特定认证方式
func (s *UserService) GetUserAuthMethod(userID int64, authType string) (*models.UserAuthMethod, error) {
	var method models.UserAuthMethod
	err := s.db.Where("user_id = ? AND auth_type = ?", userID, authType).First(&method).Error
	if err != nil {
		return nil, err
	}
	return &method, nil
}
